import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class BlocDemo extends StatefulWidget {
  const BlocDemo({Key? key}) : super(key: key);

  @override
  State<BlocDemo> createState() => _BlocDemoState();
}

class _BlocDemoState extends State<BlocDemo> {

  int t = 0;

  final cubit = CounterCubit(0);

  final bloc = CounterBloc(0);

  Stream<int> countStream(int x) async* {
    for (int i = 0; i < x; i++) {
      yield i;
    }
  }

  Stream<int> countStream2(int x) async* {
    yield* countStream2(x - 1);
  }

  Future<int> sumStream(Stream<int> stream) async {
    int sum = 0;
    await for (int m in stream) {
      sum += m;
    }
    return sum;
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Bloc")),
      body: BlocBuilder<CounterBloc, int> (
        bloc: bloc,
        buildWhen: (int a, int b) {
          print("a:$a,b:$b");
          return true;
        },
        builder: (_, int state) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text("${bloc.state}", style: TextStyle(fontSize: 20),),
              IconButton(onPressed: (){
                bloc.add(CounterPressed());
              }, icon: Icon(CupertinoIcons.calendar_badge_plus))
            ],
          );
        },
      ),
    );
  }
}

class CounterCubit extends Cubit<int> {
  CounterCubit(super.initialState);

  void increment() => emit(state + 1);

  @override
  void onChange(Change<int> change) {
    super.onChange(change);
    print("change:" + change.toString());
  }

  @override
  void onError(Object error, StackTrace stackTrace) {
    super.onError(error, stackTrace);
    print("$error, $stackTrace");
  }
}

class SimpleBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase bloc, Change change) {
    super.onChange(bloc, change);
    print("${bloc.runtimeType} $change");
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    print("${bloc.runtimeType} $transition");
  }

  @override
  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
    super.onError(bloc, error, stackTrace);
    print('${bloc.runtimeType} $error $stackTrace');
  }
}

class CounterPressed {

}

class CounterBloc extends Bloc<CounterPressed, int> {
  CounterBloc(super.initialState) {
    on((event, emit) => {
        emit(state + 1)
    });
  }

  @override
  void on<E extends CounterPressed>(EventHandler<E, int> handler, {EventTransformer<E>? transformer}) {
    super.on(handler, transformer: transformer);
    print("$handler , $transformer");
  }

  @override
  void onEvent(CounterPressed event) {
    super.onEvent(event);
    print(event);
  }

  @override
  void onChange(Change<int> change) {
    super.onChange(change);
    print(change);
  }

  @override
  void onTransition(Transition<CounterPressed, int> transition) {
    super.onTransition(transition);
    print(transition);
  }

}

// void main() {
//   final cubit = CounterCubit(0);
//   print(cubit.state);
//   cubit.increment();
//   print(cubit.state);
//   cubit.close();
// }

// void main() async {
//   SimpleBlocObserver observer = SimpleBlocObserver();
//   Bloc.observer = observer;
//   final cubit = CounterCubit(0);
//   final subs = cubit.stream.listen((event) {
//     print(event);
//   });
//   cubit.increment();
//   await Future.delayed(Duration.zero);
//   await subs.cancel();
//   await cubit.close();
// }

void main() async {
  final bloc = CounterBloc(0);
  print(bloc.state);
  bloc.add(CounterPressed());
  await Future.delayed(Duration.zero);
  print(bloc.state);
  await bloc.close();
}